package com.fzy.common.http;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.Request.Builder;

/**
 * @Desc
 * @author 冯赵杨
 * @date 2017年9月12日
 */
public class OkHttpUtil {
	private OkHttpUtil() {
	}

	//超时时间
	public static final int TIMEOUT = 1000 * 60;

	private static final String CHARSET_NAME = "UTF-8";
	public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

	private static final OkHttpClient okHttpClient = new OkHttpClient();

	static {
		okHttpClient.newBuilder().connectTimeout(TIMEOUT, TimeUnit.SECONDS).writeTimeout(TIMEOUT, TimeUnit.SECONDS)
				.readTimeout(TIMEOUT, TimeUnit.SECONDS).build();
	}

	/** 
	 * 同步get 
	 * 
	 * @param url 
	 * @return 
	 * @throws Exception 
	 */
	public static String get(String url) throws Exception {
		Builder bulider = new Request.Builder().url(url);
		Request request = bulider.build();

		Response response = execute(request);
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/** 
	 * 异步get请求 
	 * 
	 * @param url 
	 * @param responseCallback 
	 * @return 
	 * @throws Exception 
	 */
	public static void get(String url, Callback responseCallback) throws Exception {
		Request request = new Request.Builder().url(url).build();

		enqueue(request, responseCallback);
	}

	/** 
	 * 同步post json数据 
	 * 
	 * @param url 
	 * @param json 
	 * @return 
	 * @throws IOException 
	 */
	public static String post(String url, String json) throws IOException {
		RequestBody body = RequestBody.create(JSON, json);
		Request request = new Request.Builder().url(url).post(body).build();

		Response response = execute(request);
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/** 
	 * 同步post 键值对数据 
	 * 
	 * @param url 
	 * @param param 
	 * @return 
	 * @throws IOException 
	 */
	public static String post(String url, Map<String, String> param) throws IOException {
		FormBody.Builder builder = new FormBody.Builder();

		for (Map.Entry<String, String> item : param.entrySet()) {
			builder.add(item.getKey(), item.getValue());
		}

		RequestBody body = builder.build();
		Request request = new Request.Builder().url(url).post(body).build();

		Response response = execute(request);
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/** 
	 * 异步post json 
	 * 
	 * @param url 
	 * @param json 
	 * @param responseCallback 
	 * @throws IOException 
	 */
	public static void post(String url, String json, Callback responseCallback) throws IOException {
		RequestBody body = RequestBody.create(JSON, json);
		Request request = new Request.Builder().url(url).post(body).build();

		enqueue(request, responseCallback);
	}

	/** 
	 * 异步post key-value 
	 * 
	 * @param url 
	 * @param data 
	 * @param responseCallback 
	 * @throws IOException 
	 */
	public static void post(String url, Map<String, String> param, Callback responseCallback) throws IOException {
		FormBody.Builder builder = new FormBody.Builder();
		for (Map.Entry<String, String> item : param.entrySet()) {
			builder.add(item.getKey(), item.getValue());
		}

		RequestBody body = builder.build();
		Request request = new Request.Builder().url(url).post(body).build();

		enqueue(request, responseCallback);
	}

	/** 
	 * 同步put 
	 * 
	 * @param url 
	 * @param json 
	 * @return 
	 * @throws IOException 
	 */
	public static String put(String url, String json) throws IOException {
		RequestBody body = RequestBody.create(JSON, json);

		Request request = new Request.Builder().url(url).put(body).build();

		Response response = execute(request);
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/** 
	 * 同步put key-value 
	 * 
	 * @param url 
	 * @param param 
	 * @return 
	 * @throws IOException 
	 */
	public static String put(String url, Map<String, String> param) throws IOException {
		FormBody.Builder builder = new FormBody.Builder();
		for (Map.Entry<String, String> item : param.entrySet()) {
			builder.add(item.getKey(), item.getValue());
		}

		RequestBody body = builder.build();
		Request request = new Request.Builder().url(url).put(body).build();

		Response response = execute(request);
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/** 
	 * 异步put json 
	 * 
	 * @param url 
	 * @param json 
	 * @throws IOException 
	 */
	public static void put(String url, String json, Callback responseCallback) throws IOException {
		RequestBody body = RequestBody.create(JSON, json);

		Request request = new Request.Builder().url(url).put(body).build();
		enqueue(request, responseCallback);
	}

	/** 
	 * 异步put key-value 
	 * 
	 * @param url 
	 * @param param 
	 * @param responseCallback 
	 * @throws IOException 
	 */
	public static void put(String url, Map<String, String> param, Callback responseCallback) throws IOException {
		FormBody.Builder builder = new FormBody.Builder();
		for (Map.Entry<String, String> item : param.entrySet()) {
			builder.add(item.getKey(), item.getValue());
		}

		RequestBody body = builder.build();
		Request request = new Request.Builder().url(url).put(body).build();

		enqueue(request, responseCallback);
	}

	/** 
	 * 通用同步请求。 
	 * 
	 * @param request 
	 * @return 
	 * @throws IOException 
	 */
	public static Response execute(Request request) throws IOException {
		return okHttpClient.newCall(request).execute();
	}

	/** 
	 * 通用异步请求 
	 * 
	 * @param request 
	 * @param responseCallback 
	 */
	public static void enqueue(Request request, Callback responseCallback) {
		okHttpClient.newCall(request).enqueue(responseCallback);
	}

	/** 
	 * 开启异步线程访问网络, 且不在意返回结果（实现空callback） 
	 * 
	 * @param request 
	 */
	public static void enqueue(Request request) {
		okHttpClient.newCall(request).enqueue(new Callback() {

			@Override
			public void onFailure(Call call, IOException e) {
			}

			@Override
			public void onResponse(Call call, Response response) throws IOException {
			}
		});
	}

	public static String getStringFromServer(String url) throws IOException {
		Request request = new Request.Builder().url(url).build();
		Response response = execute(request);
		if (response.isSuccessful()) {
			String responseUrl = response.body().string();
			return responseUrl;
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/** 
	 * 这里使用了HttpClinet的API。只是为了方便 
	 * 
	 * @param params 
	 * @return 
	 */
	public static String formatParams(List<BasicNameValuePair> params) {
		return URLEncodedUtils.format(params, CHARSET_NAME);
	}

	/** 
	 * 为HttpGet 的 url 方便的添加多个name value 参数。 
	 * 
	 * @param url 
	 * @param params 
	 * @return 
	 */
	public static String attachHttpGetParams(String url, List<BasicNameValuePair> params) {
		return url + "?" + formatParams(params);
	}

	/** 
	 * 为HttpGet 的 url 方便的添加1个name value 参数。 
	 * 
	 * @param url 
	 * @param name 
	 * @param value 
	 * @return 
	 */
	public static String attachHttpGetParam(String url, String name, String value) {
		return url + "?" + name + "=" + value;
	}

	public static void main(String[] args) {
		try {
			String rep = OkHttpUtil.get("https://www.baidu.com");
			System.out.println(rep);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
